package com.younion.executor;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import org.apache.commons.lang.Validate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jmx.export.annotation.ManagedAttribute;
import org.springframework.jmx.export.annotation.ManagedOperation;
import org.springframework.jmx.export.annotation.ManagedResource;
import org.springframework.scheduling.support.DelegatingErrorHandlingRunnable;
import org.springframework.scheduling.support.TaskUtils;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.younion.business.IMsgTemplateService;
import com.younion.business.IRegisterUserService;
import com.younion.business.ISendMsgService;
import com.younion.common.constants.MsgStatus;
import com.younion.common.constants.Status;
import com.younion.common.exception.BaseException;
import com.younion.vo.Message;
import com.younion.vo.RegisterUserVO;
import com.younion.vo.SendMsgVO;

@ManagedResource(description = "SendExecutor Job")
public class SendMsgExecutor implements Runnable {

    private static Logger            logger          = LoggerFactory.getLogger(SendMsgExecutor.class);

    private int                      initialDelay    = 60;

    private int                      period          = 60;

    private int                      liveTime        = 7;

    private int                      shutdownTimeout = Integer.MAX_VALUE;
    
    private Map<String,String> templates  = Maps.newHashMap();

    private ScheduledExecutorService scheduledExecutorService;
    
	@Autowired
	private ISendMsgService sendMsgService = null;
	
	@Autowired
	private IMsgTemplateService msgTemplateService = null;
	
	@Autowired
	private IRegisterUserService registUserService = null;
    
    @PostConstruct
    public void start() throws Exception {
        Validate.isTrue(period > 0);
        Runnable task = new DelegatingErrorHandlingRunnable(this, TaskUtils.LOG_AND_SUPPRESS_ERROR_HANDLER);
        scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(new ThreadFactoryBuilder().setNameFormat(
                "SendMsgExecutor-%1$d").build());
        scheduledExecutorService.scheduleAtFixedRate(task, initialDelay, period, TimeUnit.SECONDS);
    }

    @PreDestroy
    public void stop() {
        try {
            scheduledExecutorService.shutdownNow();
            if (!scheduledExecutorService.awaitTermination(shutdownTimeout, TimeUnit.SECONDS)) {
                logger.warn("ScheduledThreadPool did not terminate");
            }
        } catch (InterruptedException ie) {
            Thread.currentThread().interrupt();
        }
    }

    @Override
    @ManagedOperation(description = "Executing job")
    public void run() {
        logger.debug("Scan message detecting beging");
        List<SendMsgVO> sendmsgs = getSendMsgList();
        if(sendmsgs.size() == 0){
        	logger.debug("No message to send");
        }else{
        	logger.debug("Found "+ sendmsgs.size()+ " send task");
        	for(SendMsgVO s : sendmsgs){
        		// send message immediately is the sendtime is null 
        		if(s.getSendTime() == null || s.getSendTime().before(new Date())){
        			
        		}
        	}
        }
        System.out.println(".............................Scaning messages to send.................................");
        logger.debug("Scan message detecting end");
    }
    
    private void send(List<Message> messages){
    	
    }
    
    private List<SendMsgVO> getSendMsgList(){
    	Map paramMap = Maps.newHashMap();
        paramMap.put("status", MsgStatus.UNSEND.getName());
        paramMap.put("applyStatus", Status.ACTIVE.getName());
        paramMap.put("orderBy", " send_time asc ");
         //TODO Add time fileter
        List<SendMsgVO> sendmsgs = Lists.newArrayList();
		try {
			sendmsgs = sendMsgService.getByMap(paramMap);
		} catch (BaseException e) {
			logger.debug("get send queue fail");
		}
		return sendmsgs;
    }
    
    private String generateMsgContent(SendMsgVO sendMsg){
    	String content = sendMsg.getContent();
    	List<Message> messages = Lists.newArrayList();
		try {
			if(content == null || "".equals(content)){
				content = msgTemplateService.getById(sendMsg.getTemplate().getId().toString()).getContent();
			}
			List<RegisterUserVO> users = registUserService.selectByIds(sendMsg.getUsers());
			for(String key : templates.keySet()){
				
			}
		} catch (Exception e) {
		}
		return content;
    }

    /**
     * First startup delay
     */
    public void setInitialDelay(int initialDelay) {
        this.initialDelay = initialDelay;
    }

    /**
     * Schedule period
     */
    @ManagedAttribute(description = "Job schedule period in seconds")
    public void setPeriod(int period) {
        this.period = period;
    }

    /**
     * Handled  live days
     * 
     * @param liveTime
     */
    @ManagedAttribute(description = "Handled send msg live time in days")
    public void setLiveTime(int liveTime) {
        this.liveTime = liveTime;
    }

    /**
     * Waiting time before jvm shutdown
     */
    public void setShutdownTimeout(int shutdownTimeout) {
        this.shutdownTimeout = shutdownTimeout;
    }

	public ISendMsgService getSendMsgService() {
		return sendMsgService;
	}

	public void setSendMsgService(ISendMsgService sendMsgService) {
		this.sendMsgService = sendMsgService;
	}

	public int getShutdownTimeout() {
		return shutdownTimeout;
	}

	public Map<String, String> getTemplates() {
		return templates;
	}

	public void setTemplates(Map<String, String> templates) {
		this.templates = templates;
	}
	
}
